#!/usr/bin/env python
import sm
import sys, os, os.path, re, hashlib
import multiprocessing
import FileUtilities
import Config
from LocalFile import LocalFile,AlbumInfo
import logging

def uploadImage(item):
    session,lfile = item
    iu = sm.ImageUploader(session)
    iu.upload(lfile)
    return lfile

def calcHash(localFn):
    return localFn.calcHash()

class Upload(object):
    def __init__(self, configfn):
        self.config = Config.Config(configfn)
        self.session = None
        self.pool = multiprocessing.Pool(self.config.number_of_threads)
        self.emptyDirs = {}
        logging.basicConfig(filename=self.config.logfile,level=logging.DEBUG,format="%(asctime)s - %(levelname)s - %(message)s")
        self.log = logging.debug

    def login(self):
        self.session = sm.Session(self.config.email, self.config.password)
        self.session.login()

    def createFiles(self):
        self.log('Finding files ...')
        fns = FileUtilities.findFiles(self.config.dirs, self.config.pattern, self.emptyDirs)
        self.log('Found %d files.' % (len(fns),))
        self.lfiles = [LocalFile(fn,self.config.filter) for fn in fns]

    def calcHashes(self):
        self.log('Hashing %d files ...', len(self.lfiles))
        self.lfiles = filter(lambda x: x is not None, self.pool.map(calcHash, self.lfiles))
        self.log('Files %d hashed.', len(self.lfiles))

    def createAlbumInfo(self):
        self.log('Creating album info.')
        albumNames = {}
        for lfile in self.lfiles:
            akey = os.path.dirname(lfile.fn)
            for adir in self.config.dirs:
                akey = akey.replace(adir,'')
            if akey.startswith('/'):
                akey = akey[1:]
            if len(akey) == 0:
                akey = self.config.defaultGalleryName 
            albumInfo = albumNames.get(akey,None)
            if not albumInfo:
                #info['ThemeID'] = 0
                info = {}
                info['Description'] = akey
                #info['NiceName'] = os.path.basename(akey)
                rekws = re.findall(r'\w+', akey)
                kws = []
                for rekw in rekws:
                    kws += rekw.split('_')
                info['Keywords'] = ' '.join(kws)
                albumInfo = AlbumInfo(akey, info)
                albumNames[akey] = albumInfo
            lfile.albumInfo = albumInfo
        self.log('Finished creating %d album infos.',len(albumNames))

    def getImList(self):
        self.log('Retrieving image list ...')
        albums = self.AlbumsInstance.getAlbumsByCategoryID(self.categoryID)
        ImagesInstance = sm.Images(self.session)
        self.ims = []
        for album in albums:
            self.ims += ImagesInstance.getImages(album['id'], album['Key'])
        self.log('Image list of size %d retrieved ...', len(self.ims))

    def findFilesToUpload(self):
        local = set(self.lfiles)
        remote = set(self.ims)
        self.log('local: %d remote: %d', len(local), len(remote))
        local.difference_update(remote)
        self.log('local updated: %d',len(local))
        self.lfiles = list(local)

    def createCategory(self):
        CategoriesInstance = sm.Categories(self.session)
        self.categoryID = CategoriesInstance.createCategory(self.config.category)

    def createAlbums(self):
        albums = {}
        for lfile in self.lfiles:
            albumName = lfile.albumInfo.name
            albums[albumName] = albums.get(albumName, []) + [lfile]
        self.log('creating %d albums', len(albums))
        for albumName, albumLFiles in albums.items():
            albumInfo = albumLFiles[0].albumInfo
            self.log('creating album: %s for %d files',albumName,len(albumLFiles))
            album = self.AlbumsInstance.createAlbum(albumName, self.categoryID, albumInfo)
            for lfile in albumLFiles:
                lfile.album = album
        self.log('created %d albums', len(albums))

    def upload(self):
        jobList = []
        for lfile in self.lfiles:
            jobList.append( (self.session, lfile) )
        res = self.pool.map(uploadImage, jobList)

    def run(self):
        #setup and filter files, compute md5
        self.createFiles()
        self.calcHashes()
        self.createAlbumInfo()

        #login
        self.login()
        
        self.AlbumsInstance = sm.Albums(self.session)

        #create/get category
        self.createCategory()

        #get remote file list and intersect it with local
        self.getImList()
        self.findFilesToUpload()

        self.createAlbums()
        self.upload()

def main():
    configfn = sys.argv[1]
    Upload(configfn).run()
    
if __name__ == '__main__':
    main()

# vim: set ai et sw=4 ts=4 sts=4 hlsearch
